﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.Controls;
using YArchitech.Revit;

namespace YArchitech.Plumbing
{
	public class OrderElemsBySpacing
	{
		public OrderElemsBySpacing()
		{
		}

		public OrderElemsBySpacing(ExternalCommandData externalCommandData)
		{
			this.uiDoc = externalCommandData.Application.ActiveUIDocument;
			this.doc = this.uiDoc.Document;
			this.sel = this.uiDoc.Selection;
		}

		public double GetDiameterOrWidth(Element elem, bool beCalcInsulationThickness = false)
		{
			double num = -1.0;
			int integerValue = elem.Category.Id.IntegerValue;
			if (integerValue <= -2008044)
			{
				if (integerValue != -2008132)
				{
					if (integerValue != -2008130)
					{
						if (integerValue == -2008044)
						{
							num = elem.GetParameter(BuiltInParameter.RBS_PIPE_OUTER_DIAMETER).AsDouble();
							if (beCalcInsulationThickness)
							{
								num += this.CalcInsulationThickness(elem);
							}
						}
					}
					else
					{
						num = elem.GetParameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM).AsDouble();
					}
				}
				else
				{
					num = elem.GetParameter(BuiltInParameter.RBS_CONDUIT_OUTER_DIAM_PARAM).AsDouble();
				}
			}
			else if (integerValue != -2008000)
			{
				if (integerValue != -2000051)
				{
					if (integerValue == -2000011)
					{
                        num = elem.GetParameter(BuiltInParameter.HOST_VOLUME_COMPUTED).AsDouble() / elem.GetParameter((BuiltInParameter)(-1012805)).AsDouble();
					}
				}
				else
				{
					num = 0.0;
				}
			}
			else
			{
				Parameter parameter = elem.GetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);
				Parameter parameter2 = elem.GetParameter(BuiltInParameter.RBS_CURVE_DIAMETER_PARAM);
				if (parameter != null)
				{
					num = parameter.AsDouble();
				}
				else if (parameter2 != null)
				{
					num = parameter2.AsDouble();
				}
				if (beCalcInsulationThickness)
				{
					num += this.CalcInsulationThickness(elem);
				}
			}
			return num;
		}

		private double CalcInsulationThickness(Element elem)
		{
			double result = 0.0;
			if (!(elem is Pipe) && !(elem is Duct))
			{
				return result;
			}
			Parameter parameter = elem.GetParameter(BuiltInParameter.RBS_REFERENCE_INSULATION_THICKNESS);
			if (parameter != null && parameter.HasValue)
			{
				result = parameter.AsDouble() * 2.0;
			}
			return result;
		}

		public bool JudgElemsCategory(List<Element> elemList)
		{
			bool result = true;
			int integerValue = elemList.ElementAt(0).Category.Id.IntegerValue;
			new List<int>();
			foreach (Element element in elemList)
			{
				if (integerValue != element.Category.Id.IntegerValue)
				{
					YJKMessageBox.Show("您选择的一组对象非同一类型......");
					result = false;
					break;
				}
			}
			return result;
		}

		public YJKLine GetDatumLine(out Element selectElement)
		{
			YJKLine hyline = null;
			bool flag = true;
			SelectedElement selectedElement = null;
			while (flag)
			{
				selectedElement = this.uiDoc.PickElementsByPoint("请选择基准线......", 0.05);
				if (selectedElement.Element == null || !(selectedElement.Element.Location is LocationCurve))
				{
					YJKMessageBox.Show("您选择的不能作为“排列功能”的基准线");
				}
				else
				{
					Element element = selectedElement.Element;
					XYZ xyz = selectedElement.SelectedPoint;
					if (element.Category.Id.IntegerValue == -2000530 || element.Category.Id.IntegerValue == -2000260)
					{
						YJKMessageBox.Show("您选择的不能作为“排列功能”的基准线");
					}
					else if (element.Location is LocationPoint)
					{
						YJKMessageBox.Show("您选择的不能作为“排列功能”的基准线");
					}
					else
					{
						this.baseLineLayThinkness = this.CalcInsulationThickness(element);
						LocationCurve locationCurve = element.Location as LocationCurve;
						Line line = Line.CreateBound(new XYZ(locationCurve.Curve.GetEndPoint(0).X, locationCurve.Curve.GetEndPoint(0).Y, 0.0), new XYZ(locationCurve.Curve.GetEndPoint(1).X, locationCurve.Curve.GetEndPoint(1).Y, 0.0));
						XYZ start = line.GetEndPoint(0);
						XYZ end = line.GetEndPoint(1);
						if (element.Document.IsLinked)
						{
							LinkedDocument linkedDocument = this.doc.GetLinkedDocument(element.Id);
							xyz = linkedDocument.GetPointInLinkDocument(selectedElement.SelectedPoint);
							start = linkedDocument.GetPointInLinkDocument(line.GetEndPoint(0));
							end = linkedDocument.GetPointInLinkDocument(line.GetEndPoint(1));
						}
						YJKLine hyline2 = new YJKLine(start, end);
						XYZ xyz2 = new XYZ();
						double diameterOrWidth = this.GetDiameterOrWidth(element, false);
						if (diameterOrWidth == -1.0)
						{
							YJKMessageBox.Show("您选择的不能作为“排列功能”的基准线");
						}
						else
						{
							if (diameterOrWidth == 0.0)
							{
								hyline = hyline2;
							}
							else if (diameterOrWidth > 0.0)
							{
								if (Math.Abs((line.GetEndPoint(0).X - xyz.X) * (line.GetEndPoint(1).Y - xyz.Y) - (line.GetEndPoint(1).X - xyz.X) * (line.GetEndPoint(0).Y - xyz.Y)) < 0.5)
								{
									hyline = hyline2;
								}
								else
								{
									if (hyline2.StartPoint.X != hyline2.EndPoint.X && hyline2.StartPoint.Y != hyline2.EndPoint.Y)
									{
										xyz2 = new XYZ(1.0, -(hyline2.EndPoint.X - hyline2.StartPoint.X) / (hyline2.EndPoint.Y - hyline2.StartPoint.Y), 0.0).Normalize();
									}
									else if (hyline2.StartPoint.X == hyline2.EndPoint.X)
									{
										xyz2 = new XYZ(1.0, 0.0, 0.0);
									}
									else if (hyline2.StartPoint.Y == hyline2.EndPoint.Y)
									{
										xyz2 = new XYZ(0.0, 1.0, 0.0);
									}
									Line otherLine = Line.CreateUnbound(new XYZ(xyz.X, xyz.Y, 0.0), xyz2);
									XYZ xyz3 = (hyline2.IntersectionPoint(otherLine) - new XYZ(xyz.X, xyz.Y, 0.0)).Normalize();
									hyline = new YJKLine(hyline2.StartPoint - xyz3 * diameterOrWidth / 2.0, hyline2.EndPoint - xyz3 * diameterOrWidth / 2.0);
								}
							}
							if (hyline != null)
							{
								flag = false;
							}
						}
					}
				}
			}
			selectElement = selectedElement.Element;
			return hyline;
		}

		public List<Element> GetElementsByRectangle(Element elem, YJKLine datumLine)
		{
			RectangleSelectFilter rectangleSelectFilter = new RectangleSelectFilter();
			List<Element> list = new List<Element>();
			bool flag = true;
			while (flag)
			{
				list = this.sel.PickElementsByRectangle(rectangleSelectFilter, "请框选一组风管、水管、线管或电缆桥架......").ToList<Element>();
				if (list.Count == 0)
				{
					YJKMessageBox.Show("您未获取一组对象......");
				}
				else if (this.JudgElemsCategory(list))
				{
					flag = false;
				}
			}
			List<Element> list2 = new List<Element>();
			foreach (Element element in list)
			{
				LocationCurve locationCurve = element.Location as LocationCurve;
				Line otherLine = Line.CreateBound(new XYZ(locationCurve.Curve.GetEndPoint(0).X, locationCurve.Curve.GetEndPoint(0).Y, 0.0), new XYZ(locationCurve.Curve.GetEndPoint(1).X, locationCurve.Curve.GetEndPoint(1).Y, 0.0));
				if (datumLine.IsParallel(otherLine) && elem.Id != element.Id)
				{
					list2.Add(element);
				}
			}
			return list2;
		}

		public void OrderByCentreSpacing(Dictionary<Element, double> dictionary, XYZ verticalVector, double spacing)
		{
			int num = 1;
			do
			{
				KeyValuePair<Element, double> keyValuePair = dictionary.ElementAt(0);
				double num2 = dictionary.Min((KeyValuePair<Element, double> c) => c.Value);
				foreach (KeyValuePair<Element, double> keyValuePair2 in dictionary)
				{
					if (keyValuePair2.Value == num2)
					{
						XYZ xyz = -verticalVector * ((double)num * spacing - keyValuePair2.Value);
						ElementTransformUtils.MoveElement(this.doc, keyValuePair2.Key.Id, xyz);
						keyValuePair = keyValuePair2;
						num++;
						break;
					}
				}
				dictionary.Remove(keyValuePair.Key);
			}
			while (dictionary.Count > 0);
		}

		public void OrderByOutlineSpacing(Dictionary<Element, double> dictionary, XYZ verticalVector, double spacing, bool beCalcInsulationThickness)
		{
			double num = 0.0;
			int num2 = 1;
			do
			{
				KeyValuePair<Element, double> keyValuePair = dictionary.ElementAt(0);
				double num3 = dictionary.Min((KeyValuePair<Element, double> c) => c.Value);
				foreach (KeyValuePair<Element, double> keyValuePair2 in dictionary)
				{
					if (keyValuePair2.Value == num3)
					{
						num += this.GetDiameterOrWidth(keyValuePair2.Key, beCalcInsulationThickness) * 0.5;
						if (num2 == 1)
						{
							num += this.PipeDiameter;
						}
						if (num2 == 1 && beCalcInsulationThickness)
						{
							num += this.baseLineLayThinkness / 2.0;
						}
						XYZ xyz = -verticalVector * ((double)num2 * spacing + num - keyValuePair2.Value);
						ElementTransformUtils.MoveElement(this.doc, keyValuePair2.Key.Id, xyz);
						keyValuePair = keyValuePair2;
						num2++;
						num += this.GetDiameterOrWidth(keyValuePair2.Key, beCalcInsulationThickness) * 0.5;
						break;
					}
				}
				dictionary.Remove(keyValuePair.Key);
			}
			while (dictionary.Count > 0);
		}

		private UIDocument uiDoc;

		private Document doc;

		private Selection sel;

		private double baseLineLayThinkness;

		public double PipeDiameter;
	}
}
